package com.example.designmode.proxy.dynamicproxy

import com.example.designmode.proxy.staticproxy.SellPackets
import com.example.designmode.proxy.staticproxy.TrainStation
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy


/**
 * 动态代理工厂
 * 问：ProxyFactory是代理类吗？
 * ProxyFactory不是代理类，提供了一个方法，
 * 代理类是程序运行中动态的内存中生成的类。可以
 * 通过阿里巴巴开源的Java诊断工具arthas(阿尔萨斯)查看代理类的结构
 * 在内存中生成的代理类$Proxy0
 * $Proxy0实现了SellPackets，这也印证了我们之前说的真实类和代理类实现相同的接口
 *
 * @author zhouronghua
 * @time 2022/3/10 5:20 下午
 */
class ProxyFactory {

    /**
     * 真实主题类
     */
    val trainStation = TrainStation()

    fun getProxyObject(): SellPackets {
        // 返回对象
        val proxy: SellPackets = Proxy.newProxyInstance(
            trainStation.javaClass.classLoader,
            trainStation.javaClass.interfaces,
            object : InvocationHandler {
                override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
                    println("invoke方法执行了")
                    // 方法增强
                    println("代售点收取一定的服务费用（jdk动态代理）")
                    // 通过反射调用TrainStation对象中的方法
                    /**
                     * 注意：kotlin反射调用args为空时需要使用*args.orEmpty()进行转换，否则会出错
                     * 通过反射调用真实主题类TrainStation.sell方法
                     */
                    val obj = method?.invoke(trainStation, *args.orEmpty())
                    return obj
                }
            }
        ) as SellPackets
        return proxy;
    }
}